#include "stdafx.h"
#include <algorithm>
#include "detail/bmock_expectation.hpp"

namespace bmock {
	expectation::expectation(const control_tools_ptr &t) 
		:checker_(t) {
	}

	void expectation::expect_call(const func_spec &fn,const location &loc) {
		func_ = fn;
		checker_.set_location(loc);
	}

	void expectation::expect_arguments(const arg_list &args) {
		args.save(checker_,back_inserter(arg_vals_));
	}

	void expectation::expect_call_times_range(int min_, int max_) {
		calls_.min_ = min_;
		calls_.max_ = max_;
	}

	void expectation::add_actual_call() {
		++calls_.actaul_;
	}

	bool expectation::is_last_call() const { 
		return ((!calls_.infinite_) && (calls_.max_ - calls_.actaul_ == 1)); 
	}

	bool expectation::done_minimum_calls() const { 
		return (calls_.actaul_ - calls_.min_ >=0);
	}

	result_ptr expectation::check(const func_spec &fn,const arg_list &args) const {
		checker_.check_func(func_,fn,args);		
		if(args.args_differ(checker_,arg_vals_.begin())) checker_.fail();	
		if(args.update_failed(checker_,arg_vals_.begin())) checker_.fail();
		checker_.invoke_callbacks();

		return p_result_;
	}

	void expectation::check_args_no_msg(const arg_list &args) const {
		if (args.args_differ_no_msg(checker_,arg_vals_.begin())) checker_.fail();	
	}

	bool expectation::check_non_strict(const func_spec& fn, const arg_list& args) const {
		try {
			check(fn, args);
			return true;
		}
		catch (...) {}

		return false;
	}

	result_ptr expectation::check_stub(const func_spec &fn,const arg_list &args) const
	{
		checker_.check_func(func_,fn,args);
		if(args.update_failed(checker_,arg_vals_.begin())) checker_.fail();
		checker_.invoke_callbacks();

		return p_result_;
	}

	void expectation::check_func(const func_spec &fn) const{
		if(!checker_.check_func_no_throw(func_,fn)) checker_.fail();
	}

	void expectation::not_received() {
		checker_.not_received(func_, calls_.min_, calls_.actaul_);
	}
}